﻿/*
 * Copyright (c) 2016 The ZLToolKit project authors. All Rights Reserved.
 *
 * This file is part of ZLToolKit(https://github.com/ZLMediaKit/ZLToolKit).
 *
 * Use of this m_source_map_ code is governed by MIT license that can be found in the
 * LICENSE file in the root of the m_source_map_ tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the m_source_map_ tree.
 */

#ifndef UTIL_UTIL_H_
#define UTIL_UTIL_H_

#include <ctime>
#include <cstdio>
#include <cstring>
#include <memory>
#include <string>
#include <sstream>
#include <vector>
#include <atomic>
#include <unordered_map>
#include <typeindex>
#include <iostream>
#include <functional>
#include <algorithm>
#include <type_traits>
#include <map>


#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else

#include <unistd.h>

#endif


#define INSTANCE_IMP(class_name, ...) \
class_name &class_name::Instance() { \
    static std::shared_ptr<class_name> s_instance(new class_name(__VA_ARGS__)); \
    static class_name &s_instance_ref = *s_instance; \
    return s_instance_ref; \
}

/**
 * @brief 判断 非空指针
 */
#define fast_not_null(p) (p) != NULL && (p) != nullptr

/**
 * @brief 判断 是空指针
 */
#define fast_is_null(p) (p) == NULL || (p) == nullptr

// delete object safe
#define fast_free(p)        \
    if (NULL != p) {          \
        delete p;             \
        p = NULL;             \
    }

// delete object array safe
#define fast_free_a(p)  \
    if (NULL != p) {          \
        delete []p;           \
        p = NULL;             \
    }

// 觉得该 condition 下是一个 BUG，可以添加此调试信息，查
// 看对应堆栈内容
#define BUG_ON(condition)                 \
    do {                                  \
        if (unlikely((condition) != 0)) { \
            BUG();                        \
        }                                 \
    } while (0)

// 而 WARN_ON 则是调用 dump_stack，打印堆栈信息，不会 OOPS
#define WARN_ON(condition)                                                   \
    do {                                                                     \
        if (unlikely((condition) != 0)) {                                    \
            printk(                                                          \
                "Badness in %s at %s:%d/n", __FUNCTION__, __FILE__, __LINE__ \
            );                                                               \
            dump_stack();                                                    \
        }                                                                    \
    } while (0)


typedef uint64_t hash_t;
constexpr hash_t prime = 0x100000001B3ull;
constexpr hash_t basis = 0xCBF29CE484222325ull;

constexpr inline static hash_t hash_(char const *str) {
    hash_t ret{basis};

    while (*str) {
        ret ^= *str;
        ret *= prime;
        str++;
    }

    return ret;
}

constexpr hash_t hash_compile_time(char const *str, hash_t last_value = basis) {
    return *str ? hash_compile_time(str + 1, (*str ^ last_value) * prime) : last_value;
}

/**
 * @code
 * void test_simple_switch(char const* str)
 * {
 *   using namespace std;
 *   switch(hash_(str)){
 * 	case "first"_hash:
 * 	  cout << "1st one" << endl;
 * 	  break;
 * 	case "thirfthirfthirfthir"_hash:
 * 	  cout << "2nd one" << endl;
 * 	  break;
 * 	case "thirfthirfthirfthirfthirfthirfthirg"_hash:
 * 	  cout << "3rd one" << endl;
 * 	  break;
 * 	case "thirfthirfthirfthirfthirfthirfthirf"_hash:
 * 	  cout << "4rd one" << endl;
 * 	  break;
 * 	default:
 * 	  cout << "Default..." << endl;
 *   }
 * }
 */
constexpr unsigned long long operator "" _hash(char const *p, size_t) {
    return hash_compile_time(p);
}

// 对象引用计数统计
template<class C>
class ObjectStatistic {
public:
    ObjectStatistic() {
        ++getCounter();
    }

    ~ObjectStatistic() {
        --getCounter();
    }

    static size_t count() {
        return getCounter().load();
    }

private:
    static std::atomic<size_t> &getCounter();
};

#define StatisticImp(Type)  \
    template<> \
    std::atomic<size_t>& ObjectStatistic<Type>::getCounter(){ \
        static std::atomic<size_t> instance(0); \
        return instance; \
    }


/*namespace fast {*/

class _StrPrinter : public std::string {
public:
    _StrPrinter() {}

    template<typename T>
    _StrPrinter &operator<<(T &&data) {
        _stream << std::forward<T>(data);
        this->std::string::operator=(_stream.str());
        return *this;
    }

    std::string operator<<(std::ostream &(*f)(std::ostream &)) const {
        return *this;
    }

private:
    std::stringstream _stream;
};


/**
 * @brief A class template to express an equality comparison interface.
 * @tparam T
 * @details For examples
 * @code{c++}
 * // Class value_type wants to have == and !=, so it derives from
 * // equal_comparable with itself as argument (which is the CRTP).
 * class value_type : private equal_comparable&lt;value_type> {
 *  public:
 *    bool equal_to(value_type const& rhs) const; // to be defined
 * };
 * @endcode
 */
template<typename T>
class equal_comparable {
    friend bool operator==(T const &a, T const &b) { return a.equal_to(b); }

    friend bool operator!=(T const &a, T const &b) { return !a.equal_to(b); }
};

//#define MutexGuard(x) error "Missing MutexGuard object name"

// java - synchronized ，不能在const 函数中使用  className getClassname() const {}
//#define synchronized(lock) for (MutexGuard _lock_(lock), *p = &_lock_; p != NULL; p = NULL)



// 通用输出item
# define cat_item(name) do{                                             \
    for (const auto &item: name) {                                      \
        std::cout << item.first << "   " << item.second <<std::endl;    \
    }                                                                   \
     std::cout <<"\n\n\n"<<std::endl;                                   \
}while(0);

#ifdef _WIN32
//表示windows系统，32位或64位
#ifdef _WIN64
      //64位windows系统
#endif
#elif __APPLE__
#if TARGET_IPHONE_SIMULATOR
// iOS模拟器
#elif TARGET_OS_IPHONE
// iOS设备
#elif TARGET_OS_MAC
// 其他mac系统
#else
// 未支持的其他系统
#endif
#elif __ANDROID__
//安卓系统
#elif __linux
// linux
#elif __unix
// Unix
#elif __posix
    // POSIX
#endif

#endif /* UTIL_UTIL_H_ */


















